package com.tianji.learning.service.impl;

import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.*;
import com.tianji.learning.Constants.RedisConstants;
import com.tianji.learning.domain.po.SignRecord;
import com.tianji.learning.mapper.SignRecordMapper;
import com.tianji.learning.service.ISignRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.vo.SignResultVO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 签到记录表 服务实现类
 * </p>
 *
 * @author leiyuhang
 * @since 2023-07-29
 */
@Service
@RequiredArgsConstructor
public class SignRecordServiceImpl extends ServiceImpl<SignRecordMapper, SignRecord> implements ISignRecordService {

    private final StringRedisTemplate redisTemplate;
    @Override
    public SignResultVO addSignRecords() {
        //1.1获取用户id
        Long user = UserContext.getUser();
        //1.2获取日期
        LocalDate now = LocalDate.now();
        //1.3拼接key
        String key = RedisConstants.SIGN_KEY+user+now.format(DateUtils.SIGN_DATE_SUFFIX_FORMATTER);
        //1.4计算offset
        int offset = now.getDayOfMonth()-1;
        //1.5保留签到信息
        Boolean aBoolean = redisTemplate.opsForValue().setBit(key, offset, true);
        if (BooleanUtils.isTrue(aBoolean)) {
            throw  new BizIllegalException("重复签到");
        }
        //计算连续签到天数
        int signDays = countSignDays(key, now.getDayOfMonth());
        int rewardPoints = 0;
        switch (signDays) {
            case 7: rewardPoints = 10;break;
            case 14: rewardPoints = 20;break;
            case 28: rewardPoints = 40;break;
        }
        SignResultVO vo = new SignResultVO();
        vo.setSignDays(signDays);
        vo.setRewardPoints(rewardPoints);
        return vo;
    }

    @Override
    public Byte[] recordsNum() {
        //1.1获取用户id
        Long user = UserContext.getUser();
        //1.2获取日期
        LocalDate now = LocalDate.now();
        //1.3拼接key
        String key = RedisConstants.SIGN_KEY+user+now.format(DateUtils.SIGN_DATE_SUFFIX_FORMATTER);

        List<Long> result = redisTemplate.opsForValue()
                .bitField(key, BitFieldSubCommands.create().get(
                        BitFieldSubCommands.BitFieldType.unsigned(now.getDayOfMonth())).valueAt(0));
        if (CollUtils.isEmpty(result)) {
            return null;
        }
        int i = result.get(0).intValue();
        Byte[] arr = new Byte[now.getDayOfMonth()];
        for (int i1 = arr.length-1; i1 >=0 ; i1--) {
            arr[i1] = (byte)(i & 1);
            i >>>= 1;
        }

        return arr;
    }

    private int countSignDays(String key, int dayOfMonth) {
        //获取到今天为止本月的签到数量
        List<Long> result = redisTemplate.opsForValue()
                .bitField(key, BitFieldSubCommands.create().get(
                        BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
        if (CollUtils.isEmpty(result)) {
            return 0;
        }
        int i = result.get(0).intValue();
        int count = 0;
        while ((i & 1) == 1) {
            count++;
            i >>>= 1;
        }
        return count;
    }
}
